import logging
import snakemq.link as slink
import snakemq.packeter as spacketer
import snakemq.messaging as smessaging
import snakemq.message as smessage
import threading
import datetime
import time
import json

class AlarmChecker(object):
	
	_id_prefix = "ALARMS"

	def __init__(self, id, host="localhost"):
		self.id = self._id_prefix + "_" + str(id)
		self.host = host
		self.link = slink.Link()
		self.packeter = spacketer.Packeter(self.link)
		self.messaging = smessaging.Messaging(self.id, "", self.packeter)
		self.messaging.on_message_recv.add(self.recv)
		self.alarms = {}
		self.registered_listeners = []
		self.transmit_interval = 1

	def addListener(self, port):
		print "Added listener on port %d." % port
		self.link.add_listener(("", port))

	def addConnector(self, port):
		print "Added connector on port %d." % port
		self.link.add_connector((self.host, port))

	def recv(self, conn, id, msg):
		message_data = json.loads(msg.data)
		if id.startswith("COLLECTOR"):
			if message_data["command"] == "REGISTER":
				for sensor in message_data["sensors"]:
					alarm = Alarm(sensor["name"], sensor["low"], sensor["high"])
					self.alarms[sensor["name"]] = alarm
			if message_data["command"] == "UPDATE":
				for sensor in message_data["sensors"]:
					self.alarms[sensor["name"]].check(sensor["level"])
		if id.startswith("VITALSUI"):
			if message_data["command"] == "ACKNOWLEDGE":
				self.alarms[message_data["alarm"]].acknowledge()

	def register(self, device_id):
		self.registered_listeners.append(device_id)
		payload = {"command":"REGISTER", "alarms":[]}
		for a in self.alarms.values():
			payload["alarms"].append({"name": a.id})
		payload = json.dumps(payload)
		msg = smessage.Message(payload, ttl=60)
		self.messaging.send_message(device_id, msg)
		self.registered_listeners.append(device_id)

	def update(self):
		while True:
			time.sleep(self.transmit_interval)
			payload = {"command":"UPDATE", "alarms":[]}
			for a in self.alarms.values():
				if a.in_alarm:
					payload["alarms"].append({"name": a.id})
			payload = json.dumps(payload)
			msg = smessage.Message(payload, ttl=60)
			for device_id in self.registered_listeners:
				self.messaging.send_message(device_id, msg)		

	def updateLoop(self):
		threading.Thread(target=self.update).start()

	def start(self):
		threading.Thread(target=self.link.loop).start()

# Locking alarm
class Alarm(object):
	
	def __init__(self, sensor_id, low, high):
		self.id = sensor_id
		self.low = low
		self.high = high
		self.in_alarm = None

	# Acknowledge the alarm, clearing the trouble state
	def acknowledge(self):
		self.in_alarm = None

	# If the alarm level is outside of safe ranges,
	# lock into the trouble state, setting the in_alarm
	# value to the time that the alarm was triggered.
	def check(self, level):
		if not self.in_alarm and (self.high < level or level < self.low):
			self.in_alarm = datetime.datetime.now()

